-
Notifications
You must be signed in to change notification settings - Fork 658
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: #6087 Display specific error message for course slug collision (revision) #6168
base: master
Are you sure you want to change the base?
Fix: #6087 Display specific error message for course slug collision (revision) #6168
Conversation
app/assets/javascripts/utils/api.js
Outdated
@@ -321,6 +321,10 @@ const API = { | |||
}); | |||
|
|||
if (!response.ok) { | |||
if (response.status === 422 || response.status === 400) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than special handling in JS, this should follow the pattern used elsewhere in the app where the message
from the JSON error response shown, rather than a message that is part of frontend code.
See assignments_controller.rb for some examples of this pattern, or the PR that fixed another instance of this sort of issue: #1760
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ragesoss I've made the changes you can check them. Now, the backend dynamically returns JSON error responses in all supported languages based on the selected language. I’ve also updated the screenshots for your review. Let me know if you have any feedback!
Just a suggestion, Displaying the existing course slug as a clickable link opening that existing course in a new tab so that users can easily identify which course it is colliding with by clicking on it. This will enhance clarity and user experience. |
It can be implemented, but the primary goal is to provide a clear and accurate message so that the user can choose a different slug. |
app/assets/javascripts/utils/api.js
Outdated
@@ -321,6 +321,11 @@ const API = { | |||
}); | |||
|
|||
if (!response.ok) { | |||
if (response.status === 422 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this part of the change necessary? For other errors where we display the backend message, the existing data flows work without special handling of a specific status.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A 422 response returns a JSON structure (data.errors) with a dynamically generated slug, while other responses return plain text. If special handle is not applied, it results in an empty object, failing to extract the error message and causing the default Sentry log error (e.g., "Sentry is not defined")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other cases that use this error message handling pattern don't require extra code for handling the specific status. Can you identify what is different about this, compared with (for example) #createRandomPeerAssignments
? I'd like for the error handling flow to be as simple and uniform as possible, so that most errors rely on the same code pathways without introducing new frontend code for each new case that needs user-readable error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ragesoss The code is working perfectly after removing the special Handle logic and adding a try-catch block around Sentry.captureMessage to handle failures. Unnecessary if conditions have also been removed. Please let me know if you need any more refinements.
@@ -51,6 +51,11 @@ def update | |||
ensure_passcode_set | |||
UpdateCourseWorker.schedule_edits(course: @course, editing_user: current_user) | |||
render json: { course: @course } | |||
rescue Course::DuplicateCourseSlugError => e | |||
message = I18n.t('courses.error.duplicate_slug', slug: e.slug) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not indented properly. I expect linting to fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ragesoss I have fixed the linting issues, ensuring proper formatting and readability. Let me know if you need any further improvements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like a test broke because of this new validation. You likely need to make a slight adjustment to that test so that it doesn't trigger the duplicate slug error. |
What this PR does
(Revision)
Fixes #6087
This PR addresses the issue where a generic "Internal Server Error" message was displayed when a user attempted to change a course slug to one that already existed.
Screenshots
Before:
This is an error occurring not showing proper message only showing Internal Server Error
![Screenshot (69)](https://private-user-images.githubusercontent.com/140616216/408818549-bce73cc6-2ae7-4f71-8cfd-3cf263223b8c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0MjQxMjYsIm5iZiI6MTczOTQyMzgyNiwicGF0aCI6Ii8xNDA2MTYyMTYvNDA4ODE4NTQ5LWJjZTczY2M2LTJhZTctNGY3MS04Y2ZkLTNjZjI2MzIyM2I4Yy5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxM1QwNTE3MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0yZmEwMWY3OWQ2ZDcwMzU1MGM4Nzc1NWFjMGNmNWMzOTgzNjhkZDgzZjkzYmI4YTZlMzU2ZjkzMTEwYWU1Yzg0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.KhJdwphYc6dY2XfHTELbQjo4ewdDIH5okxXiw7A4TCk)
Course titles can be identical for different organizations or institutions, but must be unique within the same organization or institution. This is because course titles are used to dynamically generate URLs (slugs), and duplicate titles within the same organization would create URL conflicts.
![Screenshot (70)](https://private-user-images.githubusercontent.com/140616216/408818551-a1eb8891-9b64-4256-9fa2-6c0856601e97.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0MjQxMjYsIm5iZiI6MTczOTQyMzgyNiwicGF0aCI6Ii8xNDA2MTYyMTYvNDA4ODE4NTUxLWExZWI4ODkxLTliNjQtNDI1Ni05ZmEyLTZjMDg1NjYwMWU5Ny5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxM1QwNTE3MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0wNDIxYTU2ZGU0NzVhZDk5M2ZmZDZjNmFiZDE1MjkwYmNhYjhmYWQ4M2E5NmMyZjcxNWFiMTk0YTQ1ODcxMmEzJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.9l-SOb4WskAr5w6nanfaX0R9gWkaVjRZsVrigdo5S50)
look: below
After:
Showing proper message
![Screenshot (75)](https://private-user-images.githubusercontent.com/140616216/411110440-87c11857-3e42-4a07-b6f7-6999bdf1a874.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0MjQxMjYsIm5iZiI6MTczOTQyMzgyNiwicGF0aCI6Ii8xNDA2MTYyMTYvNDExMTEwNDQwLTg3YzExODU3LTNlNDItNGEwNy1iNmY3LTY5OTliZGYxYTg3NC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxM1QwNTE3MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04YTA2NzVmM2EyMTU4ZWZmMjY0MTFiY2RiMTczOTI3MWZkNTJhYzNjYWE0ZWMxZDA0YmEyYTk4M2Y2MTQ4OGMyJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.70sBCc9Ru8Aji94nkzdEMr7vNDr9wtSXDfHCB_u5GAA)
![Screenshot (76)](https://private-user-images.githubusercontent.com/140616216/411110448-1a519fdd-ff88-4db3-85b5-a0c84cb45a0a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk0MjQxMjYsIm5iZiI6MTczOTQyMzgyNiwicGF0aCI6Ii8xNDA2MTYyMTYvNDExMTEwNDQ4LTFhNTE5ZmRkLWZmODgtNGRiMy04NWI1LWEwYzg0Y2I0NWEwYS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEzJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxM1QwNTE3MDZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04M2Y1MmMxNGYzM2Q0MjM1OTIzZjA2ZmJiZjk2M2I0ZTBkNTc5NWQ3MmVlMWNmN2MxYjZiMWE5MzAxZjZhZDk0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.E0EVsuABolCtJNG9PKpS1V-6UiYeQ1WyqaDYLwjw9uk)
Updated